package cn.yhbk.web.modules.ums.controller;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import cn.yhbk.web.common.Util.MinioUtils;
import cn.yhbk.web.common.api.CommonResult;
import cn.yhbk.web.common.exception.ApiException;
import cn.yhbk.web.common.service.RedisService;
import cn.yhbk.web.config.AliOSSConfig;
import cn.yhbk.web.config.MinioConfig;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectResult;
import io.minio.ObjectWriteResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import lombok.extern.slf4j.XSlf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/oss")
@Api(tags = "OOS操作")
public class OSSController {

    @Autowired
    private MinioUtils minioUtils;
    
    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private RedisService redisService;

    @Autowired
    private AliOSSConfig aliOSSConfig;

    @ApiOperation("清除缓存")
    @GetMapping("/flush")
    public CommonResult flush(){

        try {
            redisService.flush();
            return CommonResult.success("清除成功!");
        } catch (Exception e) {
            throw new ApiException("清除失败，请联系管理员!");
        }

    }

    /**
     * 文件上传
     *
     * @param file
     */
    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public CommonResult upload(@RequestPart("file") MultipartFile file) {
        try {
            //文件名
            String fileName = file.getOriginalFilename();
            String newFileName = System.currentTimeMillis() + "." + StringUtils.substringAfterLast(fileName, ".");
            //类型
            String contentType = file.getContentType();
            log.info("newFileName:{}",newFileName);
            //设置文件夹名
            newFileName = minioUtils.createDirIfNOtExist(minioConfig.getBucketName(),newFileName,contentType);

            log.info("开始上传:{}",LocalDateTime.now());
            log.info(LocalDateTime.now().toString());
            minioUtils.uploadFile(minioConfig.getBucketName(), file, newFileName, contentType);
            log.info("上传完毕:{}",LocalDateTime.now());


            Map<String, String> resMap = new HashMap<>();
            resMap.put("oldFileName",fileName);
            resMap.put("newFileName",newFileName);
            resMap.put("filePath",minioUtils.getPresignedObjectUrl(minioConfig.getBucketName(),newFileName));

            return CommonResult.success("上传成功",resMap);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.failed("上传失败");
        }
    }

    @ApiOperation("阿里文件上传")
    @PostMapping("/uploadAli")
    public CommonResult uploadAli(@RequestPart("file") MultipartFile file) {
        //获取相关配置
        String bucketName = aliOSSConfig.getBucketName();
        String endPoint = aliOSSConfig.getEndPoint();
        String accessKeyId = aliOSSConfig.getAccessKeyId();
        String accessKeySecret = aliOSSConfig.getAccessKeySecret();

        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);

        try {
            //文件名
            String fileName = file.getOriginalFilename();
            String newFileName = System.currentTimeMillis() + "." + StringUtils.substringAfterLast(fileName, ".");
            //类型
            String contentType = file.getContentType();
            log.info("newFileName:{}",newFileName);
            //设置文件夹名
            newFileName = minioUtils.createDirIfNOtExist(minioConfig.getBucketName(),newFileName,contentType);

            log.info("开始上传:{}",LocalDateTime.now());
            log.info(LocalDateTime.now().toString());

            PutObjectResult result = ossClient.putObject(bucketName, newFileName, file.getInputStream());
            log.info("上传完毕:{}",LocalDateTime.now());
            //拼装返回路径
            String filePath = null;
            if (result != null) {
                filePath = "https://"+bucketName+"."+endPoint+"/"+newFileName;
            }

            Map<String, String> resMap = new HashMap<>();
            resMap.put("oldFileName",fileName);
            resMap.put("newFileName",newFileName);
            resMap.put("filePath", filePath);

            return CommonResult.success("上传成功",resMap);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.failed("上传失败");
        } finally {
            //OSS关闭服务，不然会造成OOM
            ossClient.shutdown();
        }
    }



    @ApiOperation("文件上传测试")
    @PostMapping("/upload/test")
    public CommonResult uploadTest(@RequestPart("file") MultipartFile file) {
        try {
            String newFileName = "youhebuke";
            String contentType = file.getContentType();
            String fileName = "aaaa";
            minioUtils.uploadFile(minioConfig.getBucketName(), file, newFileName, contentType);


            Map<String, String> resMap = new HashMap<>();
            resMap.put("oldFileName",fileName);
            resMap.put("newFileName",newFileName);
            resMap.put("filePath",minioUtils.getPresignedObjectUrl(minioConfig.getBucketName(),newFileName));

            return CommonResult.success("上传成功",resMap);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.failed("上传失败");
        }
    }

    /**
     * 删除
     *
     * @param fileName
     */
    @ApiOperation("根据文件名删除文件")
    @DeleteMapping("/")
    public CommonResult delete(@RequestParam("fileName") String fileName) {

        boolean objectExist = minioUtils.isObjectExist(minioConfig.getBucketName(), fileName);
        if(!objectExist)return CommonResult.failed("该文件不存在!");
        minioUtils.removeFile(minioConfig.getBucketName(), fileName);
        return CommonResult.success("删除成功!");
    }

    /**
     * 获取文件信息
     *
     * @param fileName
     * @return
     */
    @ApiOperation("获取文件信息")
    @GetMapping("/info")
    public CommonResult getFileStatusInfo(@RequestParam("fileName") String fileName) {
        String fileStatusInfo = minioUtils.getFileStatusInfo(minioConfig.getBucketName(), fileName);
//        String[] split = fileStatusInfo.split("size=");
//        split[1]
        String substring = fileStatusInfo.substring(10).replace('=',':').trim();

        int start = substring.indexOf('T');
        int end = substring.indexOf('Z');
        log.info(substring);
        log.info(substring.substring(start,end+1));


        JSONObject entries = JSONUtil.parseObj(substring);
        return CommonResult.success(entries);
    }

    /**
     * 获取文件外链
     *
     * @param fileName
     * @return
     */
    @ApiOperation("获取文件外链")
    @GetMapping("/url")
    public CommonResult getPresignedObjectUrl(@RequestParam("fileName") String fileName) {
        String url = minioUtils.getPresignedObjectUrl(minioConfig.getBucketName(), fileName);
        return CommonResult.success(url);
    }

    /**
     * 文件下载
     *
     * @param fileName
     * @param response
     */
    @ApiOperation("文件下载")
    @GetMapping(value = "/download",produces = "application/octet-stream")
    public void download(@RequestParam("fileName") String fileName, HttpServletResponse response) {
        try {
            InputStream fileInputStream = minioUtils.getObject(minioConfig.getBucketName(), fileName);
            response.setContentType("application/octet-stream");
            response.setHeader("content-disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(fileInputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载失败");
        }
    }

}